package eu.boss.activities;

import java.io.IOException;
import java.util.ArrayList;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import eu.boss.R;
import eu.boss.controller.ShadowStatsController;
import eu.boss.http.Http;
import eu.boss.listadapters.PlayerAdapter;
import eu.boss.model.Player;

/**
 * This is the activity of the first tabwidget. Contains a listview with all players
 * 
 * @author Arnaud
 * 
 */

public class ShadowStatsActivity extends Activity {

	/**
	 * @param NEW_PLAYER_ID ID of NewPlayerActivity to recognize which activity returns a result
	 * @param SEE_STATS ID of PlayerActivity to recognize which activity returns a result
	 * @param mLvPlayers ListView containing datas
	 * @param mMapper Mapper to map JSON data
	 * @param mPositionClicked position of item clicked in the listview
	 * @param mController Service used as MVC controller
	 * @param mControllerConnection Connection with the service 
	 */
	
	private static int NEW_PLAYER_ID = 1;
	private static int SEE_STATS = 2;
	public static String FAILED = "FAILED";
	
	private ListView mLvPlayers;
	private ObjectMapper mMapper = new ObjectMapper();
	private int mPositionClicked;
	private ShadowStatsController mController;
	
	private ServiceConnection mControllerConnection = new ServiceConnection() {
		// Called when the connection with the service is established
		public void onServiceConnected(ComponentName className, IBinder service) {
			mController = ((ShadowStatsController.LocalBinder) service)
					.getService();
			mLvPlayers = (ListView) findViewById(R.id.lvPlayers);
			try {
				initiateList();
			} catch (JsonParseException e) {
				displayErrorMessage(e.toString());
			} catch (JsonMappingException e) {
				displayErrorMessage(e.toString());
			} catch (IOException e) {
				displayErrorMessage(e.toString());
			}
		}

		// Called when the connection with the service disconnects unexpectedly
		public void onServiceDisconnected(ComponentName className) {
			mController = null;
		}
	};
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);		
	}
	
	
	@Override
	protected void onStart() {
		super.onStart();
		// new intent to bind service
		Intent intent = new Intent(this, ShadowStatsController.class);
		getApplicationContext().bindService(intent, mControllerConnection, Context.BIND_AUTO_CREATE);
	}
		
	
	@Override
	protected void onResume(){
		super.onResume();
		if (mController!=null)
			updateList();
	}

	/**
	 * Initialize the listview.
	 * @throws JsonParseException
	 * @throws JsonMappingException
	 * @throws IOException
	 */
	public void initiateList() throws JsonParseException, JsonMappingException,
			IOException {
		//add a footer to "Add a new player"
		View footer = getLayoutInflater().inflate(R.layout.footer, null);
		mLvPlayers.addFooterView(footer);
		updateList();

		// putting a onClickListener on every single listview item
		mLvPlayers.setOnItemClickListener(new OnItemClickListener() {
			/**
			 * @param position
			 *            : position of the item clicked
			 */
			public void onItemClick(AdapterView<?> a, View v, int position,
					long id) {
				mPositionClicked = position;
				
				if(position < mController.getPlayersList().getPlayers().size()) {
					Player p = mController.getPlayersList().getPlayers().get(position);
					String s = null;
					try {
						// transforming a player in a json string
						s = mMapper.writeValueAsString(p);

					} catch (Exception e) {
						displayErrorMessage(e.toString());
					}
					Intent intent = new Intent(ShadowStatsActivity.this,
							PlayerActivity.class);
					Bundle objetbunble = new Bundle();

					objetbunble.putString("player", s);

					intent.putExtras(objetbunble);
					startActivityForResult(intent, SEE_STATS);
				}

				else {
					// it means user clicked on the footer (to add a new player)
					Intent intent = new Intent(ShadowStatsActivity.this,
							NewPlayerActivity.class);
					startActivityForResult(intent, NEW_PLAYER_ID);
				}
			}
		});
	}

	/**
	 * Launch at the return of UpdateStateActivity, NewPlayerActivity ands
	 * PlayerActivity
	 */
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if ((requestCode == NEW_PLAYER_ID) && (resultCode == RESULT_OK)) {
			Bundle extras = data.getExtras();

			if (extras != null && extras.containsKey("player")) {
				String player = extras.getString("player");
				mapPlayer(player);				
			}
		
		} else if ((requestCode == SEE_STATS) && (resultCode == RESULT_OK)) {
			mController.getPlayersList().getPlayers().remove(mPositionClicked);
		}
		PlayersPutTask putTask = new PlayersPutTask();
		putTask.execute();
		updateList();
	}

	/**
	 * Update list with the adapter
	 */
	public void updateList() {
			mController.getPlayersList().sort();
			PlayerAdapter adapter = new PlayerAdapter(this,
					mController.getPlayersList().getPlayers());
			mLvPlayers.setAdapter(adapter);
	}

	
	/**
	 * Build a player type with a string
	 * 
	 * @param strPlayer
	 */
	private void mapPlayer(String strPlayer) {
		Player player = null;
		try {
			player = mMapper.readValue(strPlayer, Player.class);
			mController.getPlayersList().getPlayers().add(player);
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * AsyncTask making HTTP Put request in a second thread. Updating server data
	 * 
	 * @author Arnaud
	 * 
	 */
	private class PlayersPutTask extends AsyncTask<Void, Void, String> {

		@Override
		protected String doInBackground(Void... params) {

			// PlayersListRequest 
			String url = getString(R.string.web_app_url);
			String response = null;
			Http request = new Http();

			try {
				//Creation of a pair Key/Value to put on the server and get response.
				String s = mMapper.writeValueAsString(mController.getPlayersList());
				ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
				pairs.add(new BasicNameValuePair("list", s));
				response = request.executePutRequest(url, pairs);

			} catch (JsonParseException e) {
				displayErrorMessage(e.toString());
			} catch (JsonMappingException e) {
				displayErrorMessage(e.toString());
			} catch (IllegalStateException e) {
				displayErrorMessage(e.toString());
			} catch (IOException e) {
				displayErrorMessage(e.toString());
			}
			return response;
		}
	};
	

	/**
	 * Displaying error message in an AlertDialog
	 * @param msg message to display
	 */
	private void displayErrorMessage(String msg) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getString(R.string.error));
		builder.setMessage(msg);
		builder.setPositiveButton(R.string.ok, null);
		builder.show();
	}
	
}